package com.example.apidocserver.domain.document.service.impl;

import com.example.apidocserver.domain.document.dao.ApiInfoDao;
import com.example.apidocserver.domain.document.entity.ApiInfo;
import com.example.apidocserver.domain.document.service.ApiInfoService;
import com.example.apidocserver.infrastructure.aop.UpsertAnno;
import com.example.apidocserver.infrastructure.util.entity.ApiInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 接口信息表(ApiInfo)表服务实现类
 *
 * @author makejava
 * @since 2023-02-22 23:03:29
 */
@Service("apiInfoService")
@Slf4j
public class ApiInfoServiceImpl implements ApiInfoService {
    @Resource
    private ApiInfoDao apiInfoDao;

    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ApiInfo queryById(Integer id) {
        return this.apiInfoDao.queryById(id);
    }

    /**
     * 查询所有对象
     *
     * @return 查询结果
     */
    @Override
    public List<ApiInfo> queryAll() {
        return this.apiInfoDao.queryAll();
    }

    /**
     * 根据对象查询
     *
     * @param apiInfo 筛选条件
     * @return 查询结果
     */
    @Override
    public List<ApiInfo> queryByEntity(ApiInfo apiInfo) {
        return this.apiInfoDao.queryByEntity(apiInfo);
    }

    /**
     * 新增数据
     *
     * @param apiInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ApiInfo insert(ApiInfo apiInfo) {
        this.apiInfoDao.insert(apiInfo);
        return this.apiInfoDao.queryById(apiInfo.getId());
    }

    /**
     * 修改数据
     *
     * @param apiInfo 实例对象
     * @return 实例对象
     */
    @Override
    public ApiInfo update(ApiInfo apiInfo) {
        this.apiInfoDao.update(apiInfo);
        return this.queryById(apiInfo.getId());
    }

    /**
     * 通过主键删除数据
     *
     * @param id 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer id) {
        return this.apiInfoDao.deleteById(id) > 0;
    }

    @Override
    public ApiInfo getDefApiInfo(Integer docId) {
        return this.apiInfoDao.findMinId(docId);
    }

    @Override
    public List<ApiInfo> findApiLike(ApiInfo apiInfo, Integer docId) {
        apiInfo.setApiName("%" + apiInfo.getApiName() + "%").setApiUri("%" + apiInfo.getApiUri() + "%");
        return this.apiInfoDao.findApiLike(apiInfo, docId);
    }

    @Override
    public List<ApiInfo> findAllBySpaceId(Integer spaceId) {
        return this.apiInfoDao.findAllBySpaceId(spaceId);
    }

    @Override
    public void insertOrFindBatch(List<ApiInfo> apiInfoList) {
        if (CollectionUtils.isEmpty(apiInfoList)) {
            return;
        }

        // 1.查询已有接口
        List<ApiInfo> dbList = this.apiInfoDao.findUniKeys(apiInfoList);
        Map<String, ApiInfo> dbKeyMap = dbList.stream().collect(Collectors.toMap(ApiInfoUtil::getUniKey, api -> api, (a, b) -> a));

        // 2.去除重复接口
        Map<String, List<ApiInfo>> uniKeyAndInfoMap = new HashMap<>(apiInfoList.size());
        List<ApiInfo> newList = new ArrayList<>(apiInfoList.size());
        for (ApiInfo apiInfo : apiInfoList) {
            String uniKey = ApiInfoUtil.getUniKey(apiInfo);
            if (dbKeyMap.containsKey(uniKey)) {
                ApiInfoUtil.fromToVal(dbKeyMap.get(uniKey), apiInfo);
                continue;
            }

            List<ApiInfo> apiInfos = uniKeyAndInfoMap.get(uniKey);
            if (CollectionUtils.isEmpty(apiInfos)) {
                apiInfos = new LinkedList<>();
                uniKeyAndInfoMap.put(uniKey, apiInfos);
                newList.add(apiInfo);
            }
            apiInfos.add(apiInfo);
        }

        if (newList.isEmpty()) {
            return;
        }
        apiInfoDao.insertBatch(newList);

        // 3.重复接口id赋值
        uniKeyAndInfoMap.forEach((key, val) -> {
            if (val.size() > 1) {
                ApiInfo apiInfo = val.get(0);
                for (int i = 1; i < val.size(); i++) {
                    val.get(i).setId(apiInfo.getId());
                }
            }
        });
    }

}
